home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / c / tagsgen.exe / TAGIO.C < prev    next >
C/C++ Source or Header  |  1992-03-29  |  14KB  |  393 lines

  1. /*
  2.  EPSHeader
  3.  
  4.    File: tagio.c
  5.    Author: J. Kercheval
  6.    Created: Wed, 07/17/1991  21:48:14
  7. */
  8. /*
  9.  EPSRevision History
  10.  
  11.    J. Kercheval  Sun, 08/18/1991  20:49:44  add fill_buffer()
  12.    J. Kercheval  Tue, 09/03/1991  23:25:13  add buffer_offset to fill_buffer()
  13.    J. Kercheval  Thu, 09/05/1991  20:13:01  add MergeFile()
  14.    J. Kercheval  Tue, 09/10/1991  23:55:47  add calls to external_cleanup() when exiting
  15.    J. Kercheval  Tue, 09/17/1991  19:41:16  add support for case_sensitive flag
  16.    J. Kercheval  Sat, 03/28/1992  10:26:45  add V6.0 Epsilon format
  17. */
  18.  
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <io.h>
  23.  
  24. #include "tagio.h"
  25. #include "log.h"
  26.  
  27.  
  28. /* external_cleanup() is used on exit(1) for internal error */
  29. extern void external_cleanup(void);
  30.  
  31.  
  32. /*----------------------------------------------------------------------------
  33.  *
  34.  * FillBuffer() fills the passed buffer parameter with bufsize characters
  35.  * (or as many as are available) and places and null character '\0' at the
  36.  * end of the buffer.  This routine returns TRUE if successful and FALSE if
  37.  * eof(infile) is true.  Note: if a bufsize parameter is passed and the read
  38.  * is successful for bufsize characters, then buffer[bufsize] will be
  39.  * overwritten with the null character.  Do not pass a bufsize the maximum
  40.  * size of the buffer.  This null terminated buffering scheme assumes the
  41.  * source file has no null character embedded within it.
  42.  *
  43.  ---------------------------------------------------------------------------*/
  44.  
  45. BOOLEAN FillBuffer(FILE * infile, char *buffer, long int bufsize)
  46. {
  47.     long int size;
  48.  
  49.     /* init buffer */
  50.     *buffer = '\0';
  51.  
  52.     /* return if end of file */
  53.     if (feof(infile))
  54.         return FALSE;
  55.  
  56.     /* read the buffer from the file */
  57.     size = (long int) fread((void *) buffer, (size_t) sizeof(unsigned char),
  58.                             (size_t) bufsize, infile);
  59.  
  60.     /* place the end of buffer mark and return success */
  61.     buffer[size] = '\0';
  62.     return TRUE;
  63. }
  64.  
  65.  
  66. /*----------------------------------------------------------------------------
  67.  *
  68.  * GetLine will read a line not to exceed n-1 chars from f and will return
  69.  * true if any characters parsed
  70.  *
  71.  ---------------------------------------------------------------------------*/
  72.  
  73. BOOLEAN GetLine(FILE * f, char *line, int n)
  74. {
  75.     int i;                      /* looping variable (size of line) */
  76.     char c;                     /* temporary character variable */
  77.  
  78.     /* check for end of file */
  79.     if (feof(f))
  80.         return FALSE;
  81.  
  82.     for (i = 0, c = '\0'; !feof(f) && c != '\n' && i < n - 1; i++) {
  83.  
  84.         /* get next char */
  85.         c = (char) fgetc(f);
  86.  
  87.         /* check for end of line due to n-1th character read */
  88.         if (i == n - 2) {
  89.             log_message("# getline() -- long line encountered - truncating");
  90.             do {
  91.                 c = (char) fgetc(f);
  92.             } while (!feof(f) && c != '\n');
  93.         }
  94.  
  95.         /* write the character to the line */
  96.         line[i] = c;
  97.     }
  98.  
  99.     /* zero length string and end of file return FALSE */
  100.     if (feof(f) && i == 1)
  101.         return FALSE;
  102.  
  103.     /* write end of line and return */
  104.     line[i - 1] = '\0';
  105.     return TRUE;
  106. }
  107.  
  108.  
  109. /*----------------------------------------------------------------------------
  110.  *
  111.  * OutputTag() places the tag in the correct format into the output stream
  112.  *
  113.  ---------------------------------------------------------------------------*/
  114.  
  115. void OutputTag(FILE * outfile, char *line, char *symbol, char *infname,
  116.                 long int line_number, long int char_number, Flags * flags)
  117. {
  118.     /* epsilon style output */
  119.     if (flags->oe) {
  120.         fprintf(outfile, "%s\t%s\t%ld\t%s\n",
  121.             symbol, infname, char_number, line);
  122.         return;
  123.     }
  124.  
  125.     if (flags->o5) {
  126.         fprintf(outfile, "%s;%s;%ld\n",    symbol, infname, char_number);
  127.         return;
  128.     }
  129.  
  130.     /* GNU style output */
  131.     if (flags->og) {
  132.         fprintf(outfile, "%s\t%s\t/^%s$/\n", symbol, infname, line);
  133.         return;
  134.     }
  135.  
  136.     /* spaces delimited output */
  137.     if (flags->os) {
  138.         fprintf(outfile, "%s %s %ld\n", symbol, infname, line_number);
  139.         return;
  140.     }
  141.  
  142.     /* MicroSoft Error format */
  143.     if (flags->om) {
  144.         fprintf(outfile, "%s %s(%ld)\n", symbol, infname, line_number);
  145.         return;
  146.     }
  147.  
  148.     /* not reached */
  149.     log_message("# OutputTag -- internal error - continuing");
  150.     return;
  151. }
  152.  
  153.  
  154. /*----------------------------------------------------------------------------
  155.  *
  156.  * MergeFile() will take the temporary file and merge it into the potentially
  157.  * existing tag file.  During the merge, any tags from the input files which
  158.  * were processed during this session will be deleted from the tag file to
  159.  * prevent innaccurate tagging information.
  160.  *
  161.  ---------------------------------------------------------------------------*/
  162.  
  163. #define MAX_TAGFILE_LINE_LENGTH 4096
  164. #define MAXPATH 80
  165.  
  166. void MergeFile(char *input_filename, char *output_filename,
  167.                 ArgList arglist, Flags * flags)
  168. {
  169.     FILE *input_stream;         /* file pointer used for input */
  170.     FILE *new_tag_stream;       /* file pointer used by new tag stream */
  171.     FILE *output_stream;        /* file pointer used for output */
  172.  
  173.     char line1[MAX_TAGFILE_LINE_LENGTH];        /* line for new tag file */
  174.     char line2[MAX_TAGFILE_LINE_LENGTH];        /* line for old tag file */
  175.     char tag_filename[MAXPATH]; /* intermediate used to purge old tags */
  176.  
  177.     char delim[] = " \t;(";     /* list of valid delimiters for tag format */
  178.  
  179.     char *tmp_filename;         /* intermediate file name */
  180.  
  181.     char *token_start;          /* pointer to interesting tokens on purge */
  182.     int token_length;           /* length of token at token_start */
  183.  
  184.     int compare;                /* the results of a stricmp() */
  185.  
  186.     BOOLEAN file1ret;           /* true while new tag file in not at EOF */
  187.     BOOLEAN file2ret;           /* true while old tag file in not at EOF */
  188.  
  189.     if (access(output_filename, 00)) {
  190.  
  191.         /* open the new tags file for read */
  192.         if ((new_tag_stream = fopen(input_filename, "r")) ==
  193.             (FILE *) NULL) {
  194.             log_message("# MergeFile() -- error opening input file");
  195.             external_cleanup();
  196.             exit(1);
  197.         }
  198.  
  199.         /* open the tag output file for write */
  200.         if ((output_stream = fopen(output_filename, "w")) ==
  201.             (FILE *) NULL) {
  202.             log_message("# MergeFile() -- error opening tag file");
  203.             external_cleanup();
  204.             exit(1);
  205.         }
  206.  
  207.         /* the old tag output file doesn't exist yet, just copy it over after
  208.          * placing the required header if this is the epsilon format. */
  209.         if (flags->oe) {
  210.             if (flags->sort_tags)
  211.                 fprintf(output_stream, "\tTAGS\tSORTED\n");
  212.             else
  213.                 fprintf(output_stream, "\tTAGS\tUNSORTED\n");
  214.         }
  215.         while (GetLine(new_tag_stream, line1, MAX_TAGFILE_LINE_LENGTH)) {
  216.             fprintf(output_stream, "%s\n", line1);
  217.         }
  218.  
  219.         /* close the files */
  220.         fclose(new_tag_stream);
  221.         fclose(output_stream);
  222.     }
  223.     else {
  224.  
  225.         /* create the required temporary file name */
  226.         tmp_filename = tempnam(".\\", "tg");
  227.  
  228.         /* open the old tag file */
  229.         if ((input_stream = fopen(output_filename, "r")) ==
  230.             (FILE *) NULL) {
  231.             log_message("# MergeFile() -- error opening output file");
  232.             external_cleanup();
  233.             exit(1);
  234.         }
  235.  
  236.         /* open the temporary file */
  237.         if ((output_stream = fopen(tmp_filename, "w")) ==
  238.             (FILE *) NULL) {
  239.             log_message("# MergeFile() -- error opening temporary file");
  240.             external_cleanup();
  241.             exit(1);
  242.         }
  243.                                  
  244.         /* if we are using the Epsilon tag format, ignore the header at
  245.          * the beginning of the file. */
  246.         if (flags->oe) {
  247.             if (GetLine(input_stream, line1, MAX_TAGFILE_LINE_LENGTH)) {
  248.                   fprintf(output_strea